package sf.database.dao;

import sf.common.wrapper.Page;
import sf.core.DBCascadeField;
import sf.core.DBObject;
import sf.database.dialect.DBDialect;
import sf.database.jdbc.sql.ConnectionCallback;
import sf.database.jdbc.sql.PageStrategy;
import sf.database.jdbc.sql.ResultSetCallback;
import sf.database.jdbc.sql.SQLContext;
import sf.database.meta.TableMapping;
import sf.database.support.MetadataEventListener;
import sf.database.template.CType;
import sf.dsl.DeleteDSL;
import sf.dsl.InsertDSL;
import sf.dsl.UpdateDSL;
import sf.dsl.example.Example;
import sf.dynamicsql.dao.DBDynmicSQL;
import sf.ext.gen.GenConfig;
import sf.jooq.dao.DBJooq;
import sf.querydsl.dao.DBQueryDSL;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * 数据库方法
 */
public interface DBMethod {

    /////// 执行上下文设置


    /**
     * 执行sql上下文,比如切换数据源
     * @param context 上下文
     * @return DBClient
     */
    DBClient useContext(DBContext context);

    //<<<<<<<<<<<<<<<<<< 实体类操作 >>>>>>>>>>>>>>>>>>


    /**
     * 获取dialect
     * @param readonly 是否只读
     * @return
     */
    DBDialect getDialect(boolean readonly);

    /**
     * @param clz
     * @param keyParams
     * @param <T>
     * @return
     */
    <T extends DBObject> boolean existsByPrimaryKeys(Class<T> clz, Object... keyParams);

    /**
     * @param query
     * @param <T>
     * @return
     */
    <T extends DBObject> boolean exists(T query);

    /**
     * 根据主键查询
     * @param clz       实体类
     * @param keyParams 主键参数
     * @param <T>       泛型
     * @return 实体
     */
    <T extends DBObject> T selectByPrimaryKeys(Class<T> clz, Object... keyParams);

    /**
     * 查询总数
     * @param query 查询
     * @param <T>   泛型
     * @return 实体
     */
    <T extends DBObject> long selectCount(T query);

    /**
     * 查询一条记录，如果结果不唯一则抛出异常
     * @param query 查询条件
     * @return 查询结果
     */
    <T extends DBObject> T selectOne(T query);

    /**
     * 使用select ... for update 查询数据
     * @param query 查询条件
     * @param <T>   泛型
     * @return 实体
     */
    <T extends DBObject> T selectOneForUpdate(T query);

    /**
     * 查询列表
     * @param query 查询请求。
     *              <ul>
     *              <li>如果设置了Query条件，按query条件查询。 否则——</li>
     *              <li>如果设置了主键值，按主键查询，否则——</li>
     *              <li>按所有设置过值的字段作为条件查询。</li>
     *              </ul>
     * @return 结果
     */
    <T extends DBObject> List<T> selectList(T query);

    /**
     * 查询列表
     * @param query 查询请求。
     * @param start 开始条数
     * @param limit 结束条数
     * @param <T>
     * @return
     */
    <T extends DBObject> List<T> selectList(T query, long start, int limit);

    /**
     * 使用select ... for update 查询数据
     * @param query 查询
     * @param <T>   泛型
     * @return 实体
     */
    <T extends DBObject> List<T> selectListForUpdate(T query);

    /**
     * 查询并分页
     * @param query 查询请求
     * @param start 起始记录，offset。从0开始。
     * @param limit 限制记录条数。如每页10条传入10。
     * @return 分页对象
     */
    <T extends DBObject> Page<T> selectPage(T query, long start, int limit);

    /**
     * @param clz
     * @param context
     * @param start
     * @param limit
     * @param <T>
     * @return
     */
    <T> Page<T> selectPage(Class<T> clz, SQLContext context, long start, int limit);

    /**
     * @param clz
     * @param context
     * @param <T>
     * @return
     */
    <T> T selectOne(Class<T> clz, SQLContext context);

    /**
     * @param beanClass
     * @param context
     * @param <T>
     * @return
     */
    <T> List<T> selectList(Class<T> beanClass, SQLContext context);

    /**
     * @param beanClass
     * @param context
     * @param start
     * @param limit
     * @param <T>
     * @return
     */
    <T> List<T> selectList(Class<T> beanClass, SQLContext context, long start, int limit);

    /**
     * 查询迭代结果.回调形式.
     * @param ormIt 迭代回调方法
     * @param query 查询
     * @param <T>   泛型
     */
    <T extends DBObject> void selectIterator(Consumer<Iterable<T>> ormIt, T query);

    /**
     * 查询限制条数和起始位置的迭代结果.回调形式.
     * @param ormIt 迭代回调方法
     * @param query 查询
     * @param start 起始数
     * @param limit 限制数
     * @param <T>   泛型
     */
    <T extends DBObject> void selectIterator(Consumer<Iterable<T>> ormIt, T query, long start, int limit);

    /**
     * stream lambda形式迭代结果.
     * @param ormStream 迭代回调方法
     * @param query     查询
     * @param <T>       泛型
     */
    <T extends DBObject> void selectStream(Consumer<Stream<T>> ormStream, T query);

    ///// model 执行

    /**
     * 保存
     * @param obj 实体
     * @param <T> 泛型
     * @return 执行结果
     */
    <T extends DBObject> int insert(T obj);

    /**
     * 快速插入方法,不返还主键.
     * @param obj 实体
     * @return 执行结果
     */
    <T extends DBObject> int insertFast(T obj);

    /**
     * 插入结果
     * @param obj               实体
     * @param fast              是否为快速插入
     * @param useOptimisticLock 是否使用乐观锁功能
     * @return 执行结果
     */
    <T extends DBObject> int insert(T obj, boolean fast, boolean useOptimisticLock);

    /**
     * 合并结果,根据传入主键确定是保存还是修改数据.
     * @param obj 实体
     * @param <T> 泛型
     * @return 执行结果
     */
    <T extends DBObject> int merge(T obj);

    /**
     * 更新对象(乐观锁不作为更新条件)
     * @param obj 待更新的实体
     * @return 返还执行的记录数
     */
    <T extends DBObject> int update(T obj);

    /**
     * 乐观锁, 以特定字段的值作为限制条件,更新对象,并更新该字段的值.参考字段的Java属性名.必须设置了@Version标签
     * 注意:对于时间作为乐观锁,由于数据库和java时间存在差异,如果需要设置更新后的值,需要重新调用OptimisticLock.setNewOptimisticLockValues查询方法设置最新的值.
     * 锁更新规则
     * <p>
     * 1.对于数字,则+1;<br>
     * 2.对于日期取当前时间戳.<br>
     * 3.对于字符串,取UUID的值.
     * </p>
     * <p>
     * 执行的sql如下:
     * <p/>
     * <code>update t_user set age=30, city="广州", version=version+1 where name="wendal" and version=124;</code>
     * @param obj 需要更新的对象, 必须带主键,并设置过主键的值.
     * @return 若更新成功, 返回值大于0, 否则等于0
     */
    <T extends DBObject> int updateAndSet(T obj);

    /**
     * 根据乐观锁条件更新,并会更新数据库中的乐观锁条件.但不会更新对象的乐观锁字段的值.
     * 基于版本的更新，版本不一样无法更新数据
     * @param obj 需要更新的对象, 必须有@Version属性
     * @return 若更新成功, 大于0, 否则等于0
     */
    <T extends DBObject> int updateWithVersion(T obj);


    /**
     * 警告:从数据库中获取最新的乐观锁的值到对象中,一般情况下,该方法用不到.慎用.
     * @param obj 实体
     * @param <T> 泛型
     */
    <T extends DBObject> void setNewOptimisticLockValues(T obj);

    /**
     * 根据主键删除实体
     * @param clz       实体类
     * @param keyParams 主键值
     * @param <T>       泛型
     * @return 执行结果
     */
    <T extends DBObject> int deleteByPrimaryKeys(Class<T> clz, Object... keyParams);

    /**
     * 删除实体,根据设置的值删除
     * @param obj 实体
     * @param <T> 泛型
     * @return 执行结果
     */
    <T extends DBObject> int delete(T obj);

    /**
     * @param clz       
     * @param keyParams
     * @param <T>
     * @return
     */
    <T extends DBObject> int logicDeleteByPrimaryKeys(Class<T> clz, Object... keyParams);

    /**
     * @param obj
     * @return
     */
    int logicDelete(DBObject obj);

    /**
     * 清空表数据
     * @param clz 实体类
     * @param <T> 泛型
     */
    <T extends DBObject> void truncate(Class<T> clz);

    /**
     * 批量插入
     * @param modelList 对象列表
     * @return 执行结果
     */
    int[] batchInsert(Collection<? extends DBObject> modelList);

    /**
     * 批量插入
     * @param modelList 对象列表
     * @param batchSize 每批数量
     * @return 执行结果
     */
    int[] batchInsert(Collection<? extends DBObject> modelList, int batchSize);

    /**
     * 快速插入方法
     * @param modelList 对象列表
     * @return 执行结果
     */
    int[] batchInsertFast(Collection<? extends DBObject> modelList);

    /**
     * 快速插入方法
     * @param modelList 对象列表
     * @param batchSize 每批数量
     * @return 执行结果
     */
    int[] batchInsertFast(Collection<? extends DBObject> modelList, int batchSize);

    /**
     * 更新对象,如果有乐观锁,会根据乐观锁条件更新,并会更新数据库中的乐观锁条件.但不会更新对象的乐观锁字段的值.
     * @param modelList 对象列表
     * @return 执行结果
     */
    int[] batchUpdate(Collection<? extends DBObject> modelList);

    /**
     * 更新对象,如果有乐观锁,会根据乐观锁条件更新,并会更新数据库中的乐观锁条件.但不会更新对象的乐观锁字段的值.
     * @param modelList 对象列表
     * @param batchSize 每批数量
     * @return 执行结果
     */
    int[] batchUpdate(Collection<? extends DBObject> modelList, int batchSize);

    /**
     * 批量删除
     * @param modelList 对象列表
     * @return 执行结果
     */
    int[] batchDelete(Collection<? extends DBObject> modelList);

    /**
     * 批量删除
     * @param modelList 对象列表
     * @param batchSize 每批数量
     * @return 执行结果
     */
    int[] batchDelete(Collection<? extends DBObject> modelList, int batchSize);

    /**
     * 根据表名生成对应的pojo类
     * @param pkg      包名,如 com.test
     * @param srcPath: 文件保存路径
     * @param config   配置生成的风格
     */
    void genPojoCodes(String pkg, String srcPath, GenConfig config);

    /**
     * 建表
     * @param clz 实体类
     * @return 成功与否
     */
    boolean createTable(Class<?> clz);

    /**
     * 创建全部表
     * @return 成功与否
     */
    boolean createTables();

    /**
     * 删除表
     * @param clz
     * @return
     */
    boolean dropTable(Class<?> clz);

    /**
     * 刷新表
     * @return
     */
    boolean refreshTables();

    /**
     * 刷新某张表
     * @param clz 实体类
     * @return
     */
    boolean refreshTable(Class<?> clz);

    /**
     * @param clz
     * @param listener
     */
    void refreshTable(Class<?> clz, MetadataEventListener listener);

    /**
     * @param meta
     * @param event
     * @param modifyConstraint
     * @param modifyIndexes
     * @return
     */
    boolean refreshTable(TableMapping meta, MetadataEventListener event, boolean modifyConstraint, boolean modifyIndexes);

    /**
     * 查找对象列表,并查询级联字段
     * @param query  查询
     * @param clz    实体类
     * @param fields 级联字段
     * @param <T>    泛型
     * @return 列表
     */
    <T extends DBObject> List<T> fetchCascade(T query, Class<T> clz, DBCascadeField... fields);

    /**
     * 根据一个正则表达式，获取对象所有的关联字段
     * @param obj 数据对象,不可以是Class啊!!!传对象或集合啊!!!
     * @param <T>
     * @return 更新后的数据对象本身
     * @see javax.persistence.OneToOne
     * @see javax.persistence.ManyToMany
     * @see javax.persistence.OneToMany
     */
    <T extends DBObject> T fetchLinks(T obj);

    /**
     * 根据字段，获取对象所有的关联字段
     * @param obj    数据对象,不可以是Class啊!!!传对象或集合啊!!!
     * @param fields
     * @param <T>
     * @return 更新后的数据对象本身
     * @see javax.persistence.OneToOne
     * @see javax.persistence.ManyToMany
     * @see javax.persistence.OneToMany
     */
    <T extends DBObject> T fetchLinks(T obj, DBCascadeField... fields);

    /**
     * @param context
     * @return
     */
    int execute(SQLContext context);

    /**
     * 将对象插入数据库同时，也将指定级联字段的所有关联字段关联的对象统统插入相应的数据库
     * <p>
     * 关于关联字段更多信息，请参看 '@One' | '@Many' | '@ManyMany' 更多的描述
     * @param obj
     * @param fields 指定字段,控制力度更细,至少一个或多个 描述了什么样的关联字段将被关注。如果为 null，则表示全部的关联字段都会被插入
     * @return
     */
    int insertCascade(DBObject obj, DBCascadeField... fields);

    /**
     * 仅将对象所有的关联字段插入到数据库中，并不包括对象本身
     * @param obj    数据对象
     * @param fields 字段名称，描述了什么样的关联字段将被关注。如果为 null，则表示全部的关联字段都会被插入
     * @return 数据对象本身
     * @see javax.persistence.OneToOne
     * @see javax.persistence.ManyToMany
     * @see javax.persistence.OneToMany
     */
    <T extends DBObject> T insertLinks(T obj, DBCascadeField... fields);

    /**
     * 将对象的一个或者多个，多对多的关联信息，插入数据表
     * @param obj    对象
     * @param fields 正则表达式，描述了那种多对多关联字段将被执行该操作
     * @return 对象自身
     * @see javax.persistence.ManyToMany
     */
    <T extends DBObject> T insertRelation(T obj, DBCascadeField... fields);

    /**
     * 将对象更新的同时，也将指定级联字段的所有关联字段关联的对象统统更新
     * <p>
     * 关于关联字段更多信息，请参看 '@One' | '@Many' | '@ManyMany' 更多的描述
     * @param obj    数据对象
     * @param fields 指定字段,控制力度更细,至少一个或多个,描述了什么样的关联字段将被关注。如果为 null，则表示全部的关联字段都会被更新
     * @return 执行结果
     */
    int updateCascade(DBObject obj, DBCascadeField... fields);

    /**
     * 仅更新对象所有的关联字段，并不包括对象本身
     * @param obj    数据对象
     * @param fields 字段名称，描述了什么样的关联字段将被关注。如果为 null，则表示全部的关联字段都会被更新
     * @param <T>
     * @return 对象内部更新的级联数量
     * @see javax.persistence.OneToOne
     * @see javax.persistence.ManyToMany
     * @see javax.persistence.OneToMany
     */
    <T extends DBObject> int updateLinks(T obj, DBCascadeField... fields);

    /**
     * 多对多关联是通过一个中间表将两条数据表记录关联起来。
     * <p>
     * 而这个中间表可能还有其他的字段，比如描述关联的权重等
     * <p>
     * 这个操作可以让你一次更新某一个对象中多个多对多关联的数据
     * @param obj    数据对象
     * @param fields 字段名称，描述了那种多对多关联字段将被执行该操作
     * @param <T>
     * @return 共有多少条数据被更新
     * @see javax.persistence.ManyToMany
     */
    <T extends DBObject> int updateRelation(T obj, DBCascadeField... fields);

    /**
     * 将对象删除的同时，也将指定级联字段的所有关联字段关联的对象统统删除 <b style=color:red>注意：</b>
     * <p>
     * Java 对象的字段会被保留，这里的删除，将只会删除数据库中的记录
     * <p>
     * 关于关联字段更多信息，请参看 '@One' | '@Many' | '@ManyMany' 更多的描述
     * @param obj    对象
     * @param fields 指定字段,控制力度更细,至少一个或多个 描述了什么样的关联字段将被关注。如果为 null，则表示全部的关联字段都会被删除
     * @param <T>    泛型
     * @return 执行结果
     */
    <T extends DBObject> int deleteCascade(T obj, DBCascadeField... fields);

    /**
     * 仅删除对象所有的关联字段，并不包括对象本身。 <b style=color:red>注意：</b>
     * <p>
     * Java 对象的字段会被保留，这里的删除，将只会删除数据库中的记录
     * <p>
     * 关于关联字段更多信息，请参看 '@One' | '@Many' | '@ManyMany' 更多的描述
     * @param obj    数据对象
     * @param fields 字段名称，描述了什么样的关联字段将被关注。如果为 null，则表示全部的关联字段都会被删除
     * @param <T>
     * @return 被影响的记录行数
     * @see javax.persistence.OneToOne
     * @see javax.persistence.ManyToOne
     * @see javax.persistence.ManyToMany
     */
    <T extends DBObject> int deleteLinks(T obj, DBCascadeField... fields);

    /**
     * 多对多关联是通过一个中间表将两条数据表记录关联起来。
     * <p>
     * 而这个中间表可能还有其他的字段，比如描述关联的权重等
     * <p>
     * 这个操作可以让你一次删除某一个对象中多个多对多关联的数据
     * @param obj
     * @param fields 字段名称，描述了那种多对多关联字段将被执行该操作
     * @return 共有多少条数据被更新
     * @see javax.persistence.ManyToMany
     */
    <T extends DBObject> int deleteRelation(T obj, DBCascadeField... fields);

    ///////////////////////// example 查询执行

    /**
     * @param start
     * @param limit
     * @param beanClass
     * @param example
     * @param <T>
     * @return
     */
    <T> Page<T> selectPage(long start, int limit, Class<T> beanClass, Example example);

    /**
     * @param example
     * @return
     * @
     */
    Object[] selectArray(Example example);

    /**
     * @param beanClass
     * @param example
     * @param <T>
     * @return
     * @
     */
    <T> List<T> selectList(Class<T> beanClass, Example example);

    /**
     * @param beanClass
     * @param start
     * @param limit
     * @param example
     * @param <T>
     * @return
     */
    <T> List<T> selectList(Class<T> beanClass, long start, int limit, Example example);


    /**
     * @param beanClass
     * @param example
     * @param <T>
     * @return
     */
    <T> List<T> selectListForUpdate(Class<T> beanClass, Example example);

    /**
     * @param beanClass
     * @param example
     * @param <T>
     * @return
     * @
     */
    <T> T selectOne(Class<T> beanClass, Example example);

    /**
     * @param beanClass
     * @param example
     * @param <T>
     * @return
     */
    <T> T selectOneForUpdate(Class<T> beanClass, Example example);

    /**
     * @param example
     * @return
     */
    List<Map<String, Object>> select(Example example);

    /**
     * @param insertDSL
     * @param datas     如果需要主键返回,可以放入一个空list
     * @return
     */
    int insert(InsertDSL insertDSL, List<DBObject> datas);

    /**
     * DSL更新
     * @param updateDSL
     * @return
     */
    int update(UpdateDSL updateDSL);

    /**
     * DSL删除
     * @param deleteDSL
     * @return
     */
    int delete(DeleteDSL deleteDSL);
    /////// sql 查询执行

    /**
     * 查询 map ,注意返回结果字段不区分大小写.
     * @param sql   原始语句
     * @param paras 参数
     * @return 列表
     */
    List<Map<String, Object>> select(String sql, Object... paras);

    /**
     * 查询单一对象
     * @param beanClass  实体类
     * @param sql        语句
     * @param parameters 参数
     * @param <T>        泛型
     * @return 单一对象
     */
    <T> T selectOne(Class<T> beanClass, String sql, Object... parameters);

    /**
     * @param beanClass
     * @param start
     * @param limit
     * @param sql
     * @param parameters
     * @param <T>
     * @return
     */
    <T> List<T> selectList(Class<T> beanClass, long start, int limit, String sql, Object... parameters);

    /**
     * 查询结果为数组
     * @param sql        原始语句
     * @param parameters 参数
     * @return 数组
     */
    Object[] selectArray(String sql, Object... parameters);

    /**
     * 根据sql查询,返回对应的列表
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param sql        原始语句
     * @param parameters 参数
     * @param <T>        泛型
     * @return 列表
     */
    <T> List<T> selectList(Class<T> beanClass, String sql, Object... parameters);

    /**
     * 分页查询
     * @param start      起始位置
     * @param limit      限制数量
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param sql        原始语句
     * @param parameters 参数
     * @param <T>        泛型
     * @return 分页结果
     */
    <T> Page<T> selectPage(long start, int limit, Class<T> beanClass, String sql, Object... parameters);

    /**
     * 最原始的分页方法,假分页实现,使用result跳过数据,实现
     * @param start      起始位置
     * @param limit      限制数量
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param countSql   查询总数的语句
     * @param countParas 查询总数的参数
     * @param listSql    查询列表的语句,不能包含限制条数(start和limit)的内容.
     * @param listParas  查询列表的参数
     * @param <T>        泛型
     * @return 分页结果
     */
    <T> Page<T> selectPageRaw(long start, int limit, Class<T> beanClass, String countSql, Object[] countParas, String listSql, Object[] listParas);

    /**
     * 最原始的分页方法,假分页实现,使用result跳过数据,实现
     * @param start      起始位置
     * @param limit      限制数量
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param countSql   查询总数的语句
     * @param countParas 查询总数的参数
     * @param listSql    查询列表的语句
     * @param listParas  查询列表的参数
     * @param strategy   分页策略
     * @param <T>        泛型
     * @return 分页结果
     */
    <T> Page<T> selectPageRaw(long start, int limit, Class<T> beanClass, String countSql, Object[] countParas, String listSql, Object[] listParas, PageStrategy strategy);

    /**
     * 数据迭代接口
     * @param ormIt      回调
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param sql        原始语句
     * @param parameters 参数
     * @param <T>        泛型
     */
    <T> void selectIterator(Consumer<Iterable<T>> ormIt, Class<T> beanClass, String sql, Object... parameters);

    /**
     * 是否使用假分页开启迭代模式
     * @param ormIt      回调
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param usePage    是否使用分页模式,如果为true,使用分页语句实现迭代功能
     * @param sql        原始语句
     * @param parameters 泛型
     * @param <T>        泛型
     */
    <T> void selectIterator(Consumer<Iterable<T>> ormIt, Class<T> beanClass, boolean usePage, String sql, Object... parameters);

    /**
     * 数据迭代接口
     * @param ormStream  回调
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param sql        原始语句
     * @param parameters 参数
     * @param <T>        泛型
     */
    <T> void selectStream(Consumer<Stream<T>> ormStream, Class<T> beanClass, String sql, Object... parameters);

    /**
     * 数据迭代接口
     * @param ormStream  回调
     * @param beanClass  返回结果,可以为实体类,Map,List,Object[]
     * @param usePage    是否使用分页语句实现迭代
     * @param sql        原始语句
     * @param parameters 参数
     * @param <T>        泛型
     */
    <T> void selectStream(Consumer<Stream<T>> ormStream, Class<T> beanClass, boolean usePage, String sql, Object... parameters);

    /**
     * 数据迭代接口
     * @param callback   回调
     * @param sql        原始语句
     * @param parameters 参数
     * @param <T>        泛型
     */
    <T> void selectResultSet(ResultSetCallback<T> callback, String sql, Object... parameters);

    /**
     * 数据迭代接口
     * 执行回调,主要是用于存储过程调用
     * 直接获取connection,注意连接不可手动关闭
     * @param action 回调
     * @param <T>    泛型
     * @return 结果
     */
    <T> T execute(ConnectionCallback<T> action);

    /**
     * 数据迭代接口
     * 执行回调,主要是用于存储过程调用
     * 直接获取connection,注意连接不可手动关闭
     * @param action   回调
     * @param readonly 是否只读
     * @param <T>      泛型
     * @return 结果
     */
    <T> T execute(ConnectionCallback<T> action, boolean readonly);

    /**
     * @param readonly
     * @param func
     * @param <R>
     * @return
     */
    <R> R execute(Function<DataSource, R> func, boolean readonly);

    /**
     * 回调
     * @param func
     * @param <R>
     * @return
     */
    <R> R executeFunc(Function<Connection, R> func, boolean readonly);

    /**
     * 回调
     * @param func
     * @param <R>
     * @return
     */
    <R> R executeFunc(Function<Connection, R> func);

    /**
     * 执行单一sql
     * @param sql        原始语句
     * @param parameters 参数
     * @return 执行结果
     */
    int execute(String sql, Object... parameters);

    /**
     * 批量执行SQL
     * @param sql        原始语句
     * @param parameters 参数
     * @return 执行结果
     */
    int[] executeBatch(String sql, List<Object[]> parameters);

    /**
     * @param sql
     * @param parameters
     * @param insertFast
     * @param batchSize
     * @param pkeys
     * @param keyValues
     * @return
     */
    int[] executeBatch(String sql, List<Object[]> parameters, boolean insertFast,
                       int batchSize, List<String> pkeys, List<Map<String, Object>> keyValues);

    ////////// jpa中的SqlResultSetMapping 支持 >>>>>>>>>>>>>>>>>>

    /**
     * 根据@SqlResultSetMapping设置返回值,返回的为单个对象,或数组对象
     * @param resultSetMapping @SqlResultSetMapping 中的name
     * @param sql
     * @param parameters
     * @return
     */
    List<?> selectList(String resultSetMapping, String sql, Object... parameters);

    /**
     * 根据@SqlResultSetMapping设置返回值,返回的为单个对象,或数组对象
     * @param resultSetMapping @SqlResultSetMapping 中的name
     * @param start
     * @param limit
     * @param sql
     * @param parameters
     * @return
     */
    List<?> selectList(String resultSetMapping, long start, int limit, String sql, Object... parameters);

    /**
     * 根据@SqlResultSetMapping设置返回值,返回的为单个对象,或数组对象
     * @param resultSetMapping @SqlResultSetMapping 中的name
     * @param sql
     * @param parameters
     * @return
     */
    Object selectOne(String resultSetMapping, String sql, Object... parameters);

    //// 模板ID查询执行 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    /**
     * @param sqlOrId
     * @param type
     * @param paramters
     * @return
     */
    List<Map<String, Object>> selectTemplate(String sqlOrId, CType type, Map<String, Object> paramters);

    /**
     * @param beanClass
     * @param sqlOrId
     * @param type
     * @param paramters
     * @param <T>
     * @return
     */
    <T> T selectOneTemplate(Class<T> beanClass, String sqlOrId, CType type, Map<String, Object> paramters);

    /**
     * @param sqlOrId
     * @param type
     * @param paramters
     * @return
     */
    Object[] selectArrayTemplate(String sqlOrId, CType type, Map<String, Object> paramters);

    /**
     * @param start
     * @param limit
     * @param beanClass
     * @param sqlOrId
     * @param type
     * @param paramters
     * @param <T>
     * @return
     */
    <T> Page<T> selectPageTemplate(long start, int limit, Class<T> beanClass, String sqlOrId, CType type,
                                   Map<String, Object> paramters);

    /**
     * 最原始的分页方法,使用原生sql实现
     * @param start        起始位置
     * @param limit        限制数量
     * @param beanClass    返回结果,可以为实体类,Map,List,Object[]
     * @param countSqlOrId 查询总数的语句id
     * @param countType
     * @param countParas   查询总数的参数
     * @param listSqlOrId  分页列表查询语句id,不能包含了start和limit的内容
     * @param listType
     * @param listParas    分页列表查询参数
     * @param <T>          泛型
     * @return 分页结果
     */
    <T> Page<T> selectPageRawTemplate(long start, int limit, Class<T> beanClass, String countSqlOrId, CType countType, Map<String, Object> countParas,
                                      String listSqlOrId, CType listType, Map<String, Object> listParas);

    /**
     * @param ormIt
     * @param beanClass
     * @param sqlOrId
     * @param type
     * @param parameters
     * @param <T>
     */
    <T> void selectIteratorTemplate(Consumer<Iterable<T>> ormIt, Class<T> beanClass, String sqlOrId, CType type, Map<String, Object> parameters);

    /**
     * @param ormStream
     * @param beanClass
     * @param sqlOrId
     * @param type
     * @param parameters
     * @param <T>
     */
    <T> void selectStreamTemplate(Consumer<Stream<T>> ormStream, Class<T> beanClass, String sqlOrId, CType type, Map<String, Object> parameters);

    /**
     * 带主键返回的插入
     * @param sqlOrId
     * @param type
     * @param paramters
     * @param pkeys     主键列
     * @param keyValues 可以插入值的Map,一般为new HashMap();
     * @return
     */
    int insertTemplate(String sqlOrId, CType type, Map<String, Object> paramters, List<String> pkeys, Map<String, Object> keyValues);

    /**
     * @param sqlOrId
     * @param type
     * @param paramters
     * @return
     */
    int executeTemplate(String sqlOrId, CType type, Map<String, Object> paramters);

    /**
     * @param sqlOrId
     * @param type
     * @param parameters
     * @return
     */
    int[] executeBatchTemplate(String sqlOrId, CType type, List<Map<String, Object>> parameters);

    /**
     * 批量处理,带返回主键值的功能.
     * @param sqlOrId
     * @param type
     * @param parameters
     * @param insertFast
     * @param batchSize
     * @param pkeys
     * @param keyValues
     * @return
     */
    int[] executeBatchTemplate(String sqlOrId, CType type, List<Map<String, Object>> parameters, boolean insertFast,
                               int batchSize, List<String> pkeys, List<Map<String, Object>> keyValues);

    /**
     * @param beanClass
     * @param sqlOrId
     * @param type
     * @param paramters
     * @param <T>
     * @return
     */
    <T> List<T> selectListTemplate(Class<T> beanClass, String sqlOrId, CType type, Map<String, Object> paramters);

    /**
     * @param beanClass
     * @param start
     * @param limit
     * @param sqlOrId
     * @param type
     * @param parameters
     * @param <T>
     * @return
     */
    <T> List<T> selectListTemplate(Class<T> beanClass, long start, int limit, String sqlOrId, CType type,
                                   Map<String, Object> parameters);


    //// dsl执行方法 ===================================


    /**
     * @return
     */
    DBDynmicSQL getDynmicSQL();

    ////////////////// QueryDSL支持///////////////////////

    /**
     * @return
     */
    DBQueryDSL getQueryDSL();

    ////////////////// jooq支持////////////////

    /**
     * @return
     */
    DBJooq getJooq();

    //////////////// mapper映射 ////////////////////////

    /**
     * 获取接口映射
     * @param mapperInterface 接口类
     * @param <T>             泛型
     * @return 返回值
     */
    <T> T getMapper(Class<T> mapperInterface);
}
